#ifndef __INC_MEMROY_POOL_H__
#define __INC_MEMROY_POOL_H__

#include <memory>
#include <cassert>

class memory_pool
{
public:
	memory_pool()
		:m_nMark(0),
		m_BulkSize(0),
		m_Head(0),
		m_Tail(0),
		m_AvalSize(0),
		m_pBulk(NULL),
		m_pBulkMem(NULL),
		m_nEleMentSize(0)
	{
	}

	void operator=(const memory_pool& rhs)
	{
		m_nMark = rhs.m_nMark;
		m_BulkSize = rhs.m_BulkSize;
		m_Head = rhs.m_Head;
		m_Tail = rhs.m_Tail;
		m_AvalSize = rhs.m_AvalSize;
		m_pBulk = rhs.m_pBulk;
		m_pBulkMem = rhs.m_pBulkMem;
		m_nEleMentSize = rhs.m_nEleMentSize;
	}

	int init(int nElementSize , int nBulkSize , int nMark)
	{
		m_nMark = nMark;
		assert( nBulkSize > 0 );
		assert( m_pBulkMem == NULL && m_pBulk == NULL);
		m_BulkSize = nBulkSize;
		m_nEleMentSize = nElementSize + sizeof(int);
		m_pBulkMem = new unsigned char[m_BulkSize * m_nEleMentSize ];
		m_pBulk = new _PTR[m_BulkSize];
		assert( m_pBulkMem != NULL && m_pBulk != NULL );

		unsigned char* pTmp = NULL;
		for ( int nIndex = 0; nIndex < m_BulkSize; nIndex ++ )
		{
			pTmp = m_pBulkMem + m_nEleMentSize*nIndex;
		//	*(int*)(pTmp+sizeof(ElementType)) = m_nMark;
			m_pBulk[nIndex] = pTmp;
		}
		m_Head = 0;
		m_Tail = 0;
		m_AvalSize = nBulkSize;
		return 0;
	}

	void uninit()
	{
		delete[] m_pBulkMem;
		delete[] m_pBulk;
		m_Head = 0;
		m_Tail = 0;
	}

	void* alloc()
	{
		if ( m_AvalSize == 0 )
			return new unsigned char[m_nEleMentSize];
		int nTmpHead = m_Head;
		advance_index(m_Head);
		m_AvalSize --;
		return m_pBulk[nTmpHead];
	}

	void free(void* pElement)
	{
		//assert( m_AvalSize < m_BulkSize );
	//	int n = *(int*)((unsigned char*) pElement+sizeof(ElementType));
	//	assert( *(int*)((unsigned char*) pElement+sizeof(ElementType)) == m_nMark );
		if ( pElement >= m_pBulkMem && pElement <= ( m_pBulkMem + m_BulkSize * m_nEleMentSize ) )
		{
			m_pBulk[m_Tail] = pElement;
			advance_index(m_Tail);
			m_AvalSize ++;
		}else
		{
			delete[] pElement;
		}
	}
private:
	typedef void* _PTR;
	void advance_index(int& nIndex)
	{
		if ( nIndex == (m_BulkSize-1) )
			nIndex = 0;
		else 
			nIndex ++;
	}
	
	int m_nMark;
	int m_BulkSize;
	int m_Head;
	int m_Tail;
	int m_AvalSize;
	_PTR *m_pBulk;
	unsigned char* m_pBulkMem;
	int m_nEleMentSize;
};

#define  DECLARE_MEMPOOL(ElementType)  \
public: \
void *operator new(size_t ObjectSize)  \
{ \
	return ElementType::GetMemPool().alloc(); \
} \
void operator delete(void *ptrObject, size_t ObjectSize) \
{ \
	ElementType::GetMemPool().free(ptrObject); \
} \
void operator delete(void *ptrObject ) \
{\
	ElementType::GetMemPool().free(ptrObject);\
}\
static  memory_pool& GetMemPool()\
{\
	static memory_pool _pool;\
	return _pool;\
}


#define INIT_MEMPOOL(ElementType , Size) \
ElementType::GetMemPool().init(sizeof(ElementType) , Size , 99);

#define UNINIT_MEMPOOL(ElementType) \
ElementType::GetMemPool().uninit();



#endif // __INC_MEMROY_POOL_H__

